﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace TvdP
{
    public static partial class Adapters
    {
        static Tuple<Func<A, B>, Action> MemoizedWithReset<A, B>(this Func<A, B> func)
            where A : class
            where B : class
        {
            var cache = new ConditionalWeakTable<A, B>();

            return
                Tuple.Create<Func<A, B>, Action>(
                    a =>
                    {
                        B b;

                        if (!cache.TryGetValue(a, out b))
                        {
                            b = func(a);
                            b = cache.GetValue(a, _ => b);
                        }

                        return b;
                    },
                    () => cache = new ConditionalWeakTable<A, B>()
                )
            ;
        }


        /// <summary>
        /// Internal parameter verification method.
        /// </summary>
        /// <param name="adapter"></param>
        static void CheckAdapter(IAdapters adapter)
        {
            if (adapter == null)
                throw new ArgumentNullException("adapter");
        }


        public static TTo Cast<TTo>(this IAdapters adapter, object adaptee)
            where TTo : class
        {
            return (TTo)adapter.Cast(adaptee, typeof(TTo));
        }

        public static bool CanCast<TFrom, TTo>(this IAdapters adapter)
            where TFrom : class
            where TTo : class
        {
            CheckAdapter(adapter);

            return adapter.CanCast(typeof(TFrom), typeof(TTo));
        }

    }
}
